package com.ponhu.ea2.goodsCenter.provider.facade.impl;

import com.alibaba.fastjson.JSON;
import com.ponhu.ea2.common.basic.model.ResponseBean;
import com.ponhu.ea2.dto.GoodsInfoDto;
import com.ponhu.ea2.entity.Inventory;
import com.ponhu.ea2.enums.InventoryCategoryEnum;
import com.ponhu.ea2.goodsCenter.provider.mapper.GoodsMapper;
import com.ponhu.ea2.goodsCenter.provider.mapper.InventoryMapper;
import com.ponhu.ea2.goodsCenter.provider.service.InventoryService;
import com.ponhu.ea2.goodsCenter.provider.service.OperationRecordLogsService;
import com.ponhu.ea2.goodsCenter.provider.service.PhInventoryPropertyValueMdService;
import com.ponhu.ea2.goodsCenter.provider.utils.ProBeanUtils;
import com.ponhu.ea2.ordercenter.facade.bms.OrderToGMSFacade;
import com.ponhu.ea2.ordercenter.model.vo.bms.platform.OrderToGMSVo;
import com.ponhu.ea2.scmcenter.facade.bms.goods.GoodsCenterFacade;
import com.ponhu.ea2.scmcenter.model.vo.goods.InventoryOperateVo;
import com.ponhu.ea2.service.facade.GoodsApiService;
import com.ponhu.ea2.support.exception.BusinessRuntimeException;
import com.ponhu.ea2.vo.*;
import com.ponhu.ea2.wmscenter.facade.bms.OutInStorageFacade;
import com.ponhu.ea2.wmscenter.model.bms.dto.OutInRecordLogDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.ponhu.ea2.enums.ResponseCodeEnum.*;

/**
 * @author zhaokai
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = GoodsApiService.class, timeout = 6000)
public class GoodsApiServiceImpl implements GoodsApiService {

    @Resource
    GoodsMapper goodsMapper;

    @Resource
    InventoryMapper inventoryMapper;

    @Resource
    InventoryService inventoryService;

    @Resource
    OperationRecordLogsService operationRecordLogsService;

    @Resource
    PhInventoryPropertyValueMdService propertyValueMdService;

    @DubboReference(version = "1.0.0", check = false)
    private OutInStorageFacade outInStorageFacade;

    @DubboReference(version = "1.0.0", check = false)
    private OrderToGMSFacade orderToGMSFacade;

    @DubboReference(version = "1.0.0", check = false)
    private GoodsCenterFacade goodsCenterFacade;

    @Override
    public List<GoodsInfoVo> getGoodsInfo(List<Long> ids) {
        List<GoodsInfoVo> goodsInfoVos = new ArrayList<>();
        List<GoodsInfoDto> goodsInfoDtos = goodsMapper.getGoodsInfoForWebOrder(ids);
        if (!CollectionUtils.isEmpty(goodsInfoDtos)) {
            for (GoodsInfoDto goodsInfoDto : goodsInfoDtos) {
                GoodsInfoVo goodsInfoVo = new GoodsInfoVo();
                BeanUtils.copyProperties(goodsInfoDto, goodsInfoVo);
                if (StringUtils.isNotBlank(goodsInfoDto.getImageSrc())) {
                    goodsInfoVo.setDetailImages(goodsInfoDto.getImageSrc());
                }
                goodsInfoVos.add(goodsInfoVo);
            }
        }
        return goodsInfoVos;
    }

    @Override
    public GoodsInfoVo getGoodsInfoByCode(String code) {
        return goodsMapper.getGoodsInfoByCode(code);
    }

    @Override
    public GoodsInfoForErpVo getGoodsInfoForErp(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        GoodsInfoForErpVo infoForErp = inventoryMapper.getGoodsInfoForErp(code);
        if (ObjectUtils.isNotEmpty(infoForErp)) {
            infoForErp.setInventoryTypeStr(InventoryCategoryEnum.getNameByCode(infoForErp.getInventoryType()));
            Optional<PhPropertyVo> first = propertyValueMdService.getPropertyValueList(infoForErp.getId()).stream()
                    .filter(item -> "包号".equals(item.getPropertyName())).findFirst();
            if (first.isPresent()) {
                infoForErp.setBagNumber(first.get().getPropertyValue());
            }
        }
        return infoForErp;
    }

    @Override
    public List<PhInventoryOprLogVo> getOprLogsByInventoryCode(String inventoryCode) {
        try {
            // 查询采购中心操作日志
            CompletableFuture<List<PhInventoryOprLogVo>> cmsFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    ResponseBean<List<InventoryOperateVo>> responseBean = goodsCenterFacade.getProcurementOperateList(inventoryCode);
                    log.error("getOprLogsByInventoryCode ===>> 查询采购中心操作日志={}", JSON.toJSONString(responseBean));
                    if (responseBean.getCode() != 200) throw new RuntimeException();

                    List<InventoryOperateVo> cmsLogs = responseBean.getData();
                    return cmsLogs.stream().map(log -> ProBeanUtils.copyProperties(log, PhInventoryOprLogVo.class)).collect(Collectors.toList());
                } catch (Exception e) {
                    log.error("getOprLogsByInventoryCode ===>> Error={}", INVENTORY_OPR_LOGS_EXCEPTION_800225.getMsg());
                    throw new BusinessRuntimeException(INVENTORY_OPR_LOGS_EXCEPTION_800225);
                }
            });

            // 查询商品中心操作日志
            CompletableFuture<List<PhInventoryOprLogVo>> goodsFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    Inventory inventory = inventoryService.getInventoryByCode(inventoryCode);
                    return operationRecordLogsService.getAllLogsByRecordId(inventory.getId())
                            .stream().map(log -> new PhInventoryOprLogVo().setDocNo(inventoryCode).setDocType("货品编码")
                                    .setOperatorTime(LocalDateTime.ofInstant(log.getCreateTime().toInstant(), ZoneId.systemDefault()))
                                    .setOperatorName(log.getOperator()).setOperatorEvent(log.getTextContent())).collect(Collectors.toList());
                } catch (Exception e) {
                    log.error("getOprLogsByInventoryCode ===>> Error={}", INVENTORY_OPR_LOGS_EXCEPTION_800226.getMsg());
                    throw new BusinessRuntimeException(INVENTORY_OPR_LOGS_EXCEPTION_800226);
                }
            });

            // 查询订单中心操作日志
            CompletableFuture<List<PhInventoryOprLogVo>> omsFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    ResponseBean<List<OrderToGMSVo>> responseBean = orderToGMSFacade.listOrderByInventoryCode(inventoryCode);
                    log.error("getOprLogsByInventoryCode ===>> 查询订单中心操作日志={}", JSON.toJSONString(responseBean));
                    if (responseBean.getCode() != 200) throw new RuntimeException();

                    List<OrderToGMSVo> omsLogs = responseBean.getData();
                    return omsLogs.stream().map(log -> ProBeanUtils.copyProperties(log, PhInventoryOprLogVo.class)).collect(Collectors.toList());
                } catch (Exception e) {
                    log.error("getOprLogsByInventoryCode ===>> Error={}", INVENTORY_OPR_LOGS_EXCEPTION_800227.getMsg());
                    throw new BusinessRuntimeException(INVENTORY_OPR_LOGS_EXCEPTION_800227);
                }
            });

            // 查询任务中心操作日志
            CompletableFuture<List<PhInventoryOprLogVo>> wmsFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    ResponseBean responseBean = outInStorageFacade.listOutInRecordLogInfo(inventoryCode);
                    log.error("getOprLogsByInventoryCode ===>> 查询任务中心操作日志={}", JSON.toJSONString(responseBean));
                    if (responseBean.getCode() != 200) throw new RuntimeException();

                    List<OutInRecordLogDto> cmsLogs = (List<OutInRecordLogDto>) responseBean.getData();
                    return cmsLogs.stream().map(log -> ProBeanUtils.copyProperties(log, PhInventoryOprLogVo.class)).collect(Collectors.toList());
                } catch (Exception e) {
                    log.error("getOprLogsByInventoryCode ===>> Error={}", INVENTORY_OPR_LOGS_EXCEPTION_800228.getMsg());
                    throw new BusinessRuntimeException(INVENTORY_OPR_LOGS_EXCEPTION_800228);
                }
            });

            // 排序汇总
            return CompletableFuture.allOf(cmsFuture, goodsFuture, omsFuture, wmsFuture).thenApplyAsync(x -> {
                try {
                    List<PhInventoryOprLogVo> logVoList = Lists.newArrayList();
                    logVoList.addAll(cmsFuture.join());
                    logVoList.addAll(goodsFuture.join());
                    logVoList.addAll(omsFuture.join());
                    logVoList.addAll(wmsFuture.join());
                    return logVoList.stream().sorted((log1, log2) -> log2.getOperatorTime().compareTo(log1.getOperatorTime())).collect(Collectors.toList());
                } catch (Exception e) {
                    log.error("getOprLogsByInventoryCode ===>> Error={}", INVENTORY_OPR_LOGS_EXCEPTION_800229.getMsg());
                    throw new BusinessRuntimeException(INVENTORY_OPR_LOGS_EXCEPTION_800229);
                }
            }).get();
        } catch (Exception e) {
            if (e.getCause() instanceof BusinessRuntimeException)
                throw (BusinessRuntimeException) e.getCause();
            return null;
        }
    }

}
